/*
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 *
 * Copyright @2008 the original author or authors.
 */
package com.bluestone.action;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLEncoder;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.httpclient.URI;
import org.parosproxy.paros.core.proxy.ProxyListener;
import org.parosproxy.paros.network.HttpHeader;
import org.parosproxy.paros.network.HttpMessage;

import com.bluestone.BaseAction;
import com.bluestone.assertor.IAssertor;
import com.bluestone.context.IContext;
import com.bluestone.extension.paros.ProxyServer;
import com.bluestone.extension.totalvalidator.Section508Validation;
import com.bluestone.scripts.ActionScript;
import com.bluestone.scripts.Function;
import com.bluestone.util.Util;

/**
 * CallFuntionAction can execute a function.
 * 
 * @author <a href="mailto:bluesotne.master@gmail.com">daniel.q</a>
 */
public class Section508aAction extends BaseAction {

	public Section508aAction(ActionScript action) {
		super(action);
	}

	Vector rules = new Vector();

	/**
	 * This action can execute a query.
	 * 
	 * @return false
	 */

	public boolean execute(IContext context) {

		boolean result = false;
		try {
			long starttime = System.currentTimeMillis();
			if (action.getPara("reportfile") != null && action.getPara("reportfile").length() > 0) {
				summaryFile = summaryFile + "" + action.getPara("reportfile");
			} else {
				summaryFile = summaryFile + "section508a";
			}

			String excludes = action.getPara("excludes");
			// add rules
			ImgPolicy imgPolicy = new ImgPolicy();
			imgPolicy.name = "img";
			imgPolicy.desc = section508a_img_noalt;
			imgPolicy.reportfile = summaryFile + "img.html";
			imgPolicy.excludes = excludes;

			ObjectPolicy objPolicy = new ObjectPolicy();
			objPolicy.name = "object";
			objPolicy.desc = section508a_object;
			objPolicy.reportfile = summaryFile + "object.html";
			objPolicy.excludes = excludes;

			IframePolicy iframePolicy = new IframePolicy();
			iframePolicy.name = "iframe_notitle_noalternate";
			iframePolicy.desc = section508a_iframe_title_alternate;
			iframePolicy.reportfile = summaryFile + "iframe.html";
			iframePolicy.excludes = excludes;

			NoscriptPolicy noscriptPolicy = new NoscriptPolicy();
			noscriptPolicy.name = "script_noscript";
			noscriptPolicy.desc = section508a_script_noscripttag;
			noscriptPolicy.reportfile = summaryFile + "script_noscript.html";
			noscriptPolicy.excludes = excludes;

			CssPolicy cssPolicy = new CssPolicy();
			cssPolicy.name = "css_background";
			cssPolicy.desc = section508a_css_background;
			cssPolicy.reportfile = summaryFile + "css_background.html";
			cssPolicy.excludes = excludes;

			FramesetPolicy framesetPolicy = new FramesetPolicy();
			framesetPolicy.name = "frameset";
			framesetPolicy.desc = section508a_frameset;
			framesetPolicy.reportfile = summaryFile + "frameset.html";
			framesetPolicy.excludes = excludes;

			AppletPolicy appletPolicy = new AppletPolicy();
			appletPolicy.name = "applet";
			appletPolicy.desc = section508a_applet;
			appletPolicy.reportfile = summaryFile + "applet.html";
			appletPolicy.excludes = excludes;

			FontPolicy fontPolicy = new FontPolicy();
			fontPolicy.name = "font";
			fontPolicy.desc = section508a_font;
			fontPolicy.reportfile = summaryFile + "font.html";
			fontPolicy.excludes = excludes;

			AC360Policy ac360Policy = new AC360Policy();
			ac360Policy.name = "ac360";
			ac360Policy.desc = section508a_ac360;
			ac360Policy.reportfile = summaryFile + "ac360.html";
			ac360Policy.excludes = excludes;

			HtmlFormPolicy formPolicy = new HtmlFormPolicy();
			formPolicy.name = "form";
			formPolicy.desc = section508a_form;
			formPolicy.reportfile = summaryFile + "form.html";
			formPolicy.excludes = excludes;

			JavascriptPolicy jsPolicy = new JavascriptPolicy();
			jsPolicy.name = "javascript";
			jsPolicy.desc = section508a_javascript;
			jsPolicy.reportfile = summaryFile + "javascript.html";
			jsPolicy.excludes = excludes;

			ErrorsPolicy errorsPolicy = new ErrorsPolicy();
			errorsPolicy.name = "htmlerrors";
			errorsPolicy.desc = section508a_htmlerrors;
			errorsPolicy.reportfile = summaryFile + "htmlerrors.html";
			errorsPolicy.excludes = excludes;

			DoubleAltTitlePolicy doubleAltTitlePolicy = new DoubleAltTitlePolicy();
			doubleAltTitlePolicy.name = "doublealttitle";
			doubleAltTitlePolicy.desc = section508a_doublealttitle;
			doubleAltTitlePolicy.reportfile = summaryFile + "doublealttitle.html";
			doubleAltTitlePolicy.excludes = excludes;

			
			 rules.add(imgPolicy);
			 rules.add(objPolicy);
			 rules.add(iframePolicy);
			// rules.add(noscriptPolicy);
			//rules.add(cssPolicy);
			rules.add(framesetPolicy);
			rules.add(appletPolicy);
			rules.add(fontPolicy);
			rules.add(ac360Policy);
			rules.add(formPolicy);
			
			rules.add(jsPolicy);
			
			rules.add(errorsPolicy);
			 
			//rules.add(doubleAltTitlePolicy);

			String path = action.getPara("folder");
			if (path == null) {
				path = ".";
			}
			File root = new File(path);
			if (root.exists()) {
				checkSection508a(root);
			}
			result = true;

		} catch (Exception me) {
			me.printStackTrace();
			Util.getLogger().error(me);
		}
		return result;
	}

	private void checkSection508a(File file) {
		if (file.isFile()) {
			String[] types = null;
			if (action.getPara("filetypes") != null && action.getPara("filetypes").length() > 0) {

				types = action.getPara("filetypes").split(",");
				for (String type : types) {
					if (type.length() > 0 && file.getName().endsWith(type)) {

						checkSection508a(readFile(file), file.getAbsolutePath());
						return;
					}
				}
				int pos = file.getName().lastIndexOf(".");
				if (pos != -1) {
					String fileType = file.getName().substring(pos);
				}
			} else {
				checkSection508a(readFile(file), file.getAbsolutePath());
				return;
			}
		} else {
			File[] files = file.listFiles();
			for (File f : files) {
				checkSection508a(f);
			}
		}
	}

	byte[] bytes = new byte[1024*100];

	String readFile(File file) {
		StringBuffer buffer = new StringBuffer();
		try {
			FileInputStream in = new FileInputStream(file);
			int count = 0;
			while ((count = in.read(bytes)) > 0) {
				buffer.append(new String(bytes, 0, count));
			}
			in.close();
		} catch (Exception me) {

		}
		return buffer.toString();
	}

	public void checkSection508a(String content, String checkfile) {
		//System.out.println(checkfile);
		if(checkfile.indexOf("dsp_AgnMnInput.cfm")>0){
			System.out.println(checkfile);
		}
		// revmoe comment content?
		String t1 = "<!--";
		String t2 = "-->";
		while (true) {
			int pos1 = content.indexOf(t1);
			if (pos1 == -1) {
				break;
			}
			int pos2 = content.indexOf(t2, pos1);
			if (pos2 == -1) {
				break;
			}
			int nextpos = content.substring(0,pos2).lastIndexOf(t1);
			if(nextpos < pos2 && nextpos!=-1){
				pos1 = nextpos;
			}
			content = content.substring(0, pos1) + content.substring(pos2 + 3);
		}

		t1 = "<%--";
		t2 = "--%>";
		while (true) {
			int pos1 = content.indexOf(t1);
			if (pos1 == -1) {
				break;
			}
			int pos2 = content.indexOf(t2, pos1);
			if (pos2 == -1) {
				break;
			}
			int nextpos = content.indexOf(t1,pos1+4);
			if(nextpos < pos2 && nextpos!=-1){
				pos1 = nextpos;
			}
			content = content.substring(0, pos1) + content.substring(pos2 + 4);
		}
		
		t1 = "/*";
		t2 = "*/";
		while (true) {
			int pos1 = content.indexOf(t1);
			if (pos1 == -1) {
				break;
			}
			int pos2 = content.indexOf(t2, pos1);
			if (pos2 == -1) {
				break;
			}
			int nextpos = content.indexOf(t1,pos1+2);
			if(nextpos < pos2 && nextpos!=-1){
				pos1 = nextpos;
			}
			try{
				content = content.substring(0, pos1) + content.substring(pos2 + 2);
			}catch(Exception me){
				me.printStackTrace();
			}
		}		
		
		content = content.replaceAll("//.*", "");
		
		if(checkfile.lastIndexOf(".jsp")>0 || checkfile.lastIndexOf(".cfm")>0 || checkfile.lastIndexOf(".aspx")>0){
			content = content.replaceAll("[\r\n\t]", " ").replaceAll(" +", " ");		
			content = content.replaceAll("> *<", ">\r\n<");
		}
		for (int i = 0; i < rules.size(); i++) {
			
			Section508Policy policy = (Section508Policy) rules.get(i);
			if (!policy.isExclude(checkfile)) {
				
				Vector errors = policy.verify(content, checkfile);
				if (errors.size() > 0) {

					String scanReportFile = outputScanReport("../../"
							+ policy.reportfile, checkfile, errors);
					Section508Report scanRreport = new Section508Report(
							checkfile, "../" + scanReportFile, errors.size());
					policy.addScanReport(scanRreport);
				}
				outputSummaryReport(policy);
			}
		}

	}

	private void outputSummaryReport(Section508Policy policy) {
		//doesn't output summaryreport if error=0
		if(policy.errorCount==0){
			return;
		}
		StringBuilder stringbuilder = new StringBuilder();
		stringbuilder
				.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
		stringbuilder
				.append("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en-GB\" lang=\"en-GB\">");
		stringbuilder
				.append("<head><meta http-equiv=\"content-type\" content=\"application/xhtml+xml; charset=UTF-8\" /><link rel=\"shortcut icon\" href=\"http://www.totalvalidator.com/favicon.ico\" type=\"image/x-icon\" /><title>Total Validator Results</title><meta name=\"author\" content=\"Total Validator\" /><link rel=\"stylesheet\" href=\"../images/mainstyle.css\" /></head>");
		stringbuilder.append("<body>");
		stringbuilder.append("<h2>Summary</h2>");
		stringbuilder.append("<table summary=\"Summary of tests\">");
		stringbuilder
				.append("<tr><td class=\"nowrapl\">Started at:</td><td colspan=\"3\">"
						+ new Date(policy.starttime).toLocaleString()
						+ "</td></tr>");
		stringbuilder
				.append("<tr><td class=\"nowrapl\">Time taken:</td><td class=\"rhs\">"
						+ ((System.currentTimeMillis() - policy.starttime) / (1000 * 60))
						+ "minutes</td></tr>");
		stringbuilder
				.append("<tr><td class=\"nowrapl\">Total errors found:</td><td class=\"rhs\">"
						+ policy.errorCount + "</td></tr>");
		stringbuilder
				.append("<tr><td class=\"nowrapl\">Total scan files:</td><td class=\"rhs\">"
						+ (policy.correctFileCount + policy.errorFileCount)
						+ "</td></tr>");
		stringbuilder
				.append("<tr><td class=\"nowrapl\">Total pass files:</td><td class=\"rhs\">"
						+ (policy.correctFileCount) + "</td></tr>");
		stringbuilder
				.append("<tr><td class=\"nowrapl\">Total error files:</td><td class=\"rhs\">"
						+ (policy.errorFileCount) + "</td></tr>");
		stringbuilder.append("</table>");
		stringbuilder
				.append("<p><span class=\"strong\">Options:</span></p><ul><li>"
						+ policy.desc + "</li></ul>");

		stringbuilder.append("<h2>Validation results</h2>");
		for (int j = 0; j < policy.reports.size(); j++) {
			Section508Report report = (Section508Report) policy.reports.get(j);
			stringbuilder.append("<p><span class=\"strong\">" + report.filepath
					+ "<br/>");
			stringbuilder.append("<a href='" + report.reportlink + "'>"
					+ report.errorCounts + " error(s)</a></span></p>");
		}
		stringbuilder.append("</body></html>");

		try {
			File file = new File(policy.reportfile);
			file.getParentFile().mkdirs();

			java.io.FileOutputStream out = new java.io.FileOutputStream(file);
			out.write(stringbuilder.toString().getBytes());
			out.flush();
			out.close();

		} catch (Exception me) {
			me.printStackTrace();
		}

	}

	private String outputScanReport(String summaryfile, String checkfile,
			Vector errors) {
		String reportfile = "./section508/section508a/"
				+ System.currentTimeMillis() + ".html";
		StringBuilder stringbuilder = new StringBuilder();
		stringbuilder
				.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
		stringbuilder
				.append("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en-GB\" lang=\"en-GB\">");
		stringbuilder
				.append("<head><meta http-equiv=\"content-type\" content=\"application/xhtml+xml; charset=UTF-8\" /><link rel=\"shortcut icon\" href=\"http://www.totalvalidator.com/favicon.ico\" type=\"image/x-icon\" /><title>Total Validator Results</title><meta name=\"author\" content=\"Total Validator\" /><link rel=\"stylesheet\" href=\"../images/mainstyle.css\" /></head>");
		stringbuilder.append("<body>");
		stringbuilder
				.append("<h2><a id=\"summary\" name=\"summary\"></a>Summary</h2>");
		stringbuilder
				.append("<table summary=\"Summary of tests\"><tr><td class=\"nowrapl\">File checked:</td><td class=\"rhs\"><a href=\""
						+ checkfile
						+ "\">"
						+ checkfile
						+ "</a></td></tr><tr><td class=\"nowrapl\">Total errors found:</td><td class=\"rhs\">"
						+ errors.size()
						+ "</td></tr><tr><td class=\"nowrapl\"></td></tr></table>");
		stringbuilder
				.append("<p><span class=\"strong\"><a id=\"p0\" name=\"p0\"></a><a id=\"p164\" name=\"p164\"></a><a href=\""
						+ summaryfile
						+ "\">Back to website summary</a></span></p>");
		stringbuilder.append("<pre>");
		for (int i = 0; i < errors.size(); i++) {
			Section508Error error = (Section508Error) errors.get(i);
			stringbuilder.append("error" + (i + 1) + ":\r\n");
			stringbuilder.append("message:" + error.errormsg + "\r\n");
			stringbuilder.append(markupTags(error.content) + "\r\n");
			stringbuilder.append("\r\n\r\n");
		}
		stringbuilder.append("");
		stringbuilder.append("</pre>");
		stringbuilder.append("</body></html>");
		stringbuilder.append("");
		try {
			File file = new File(reportfile);
			file.getParentFile().mkdirs();

			java.io.FileOutputStream out = new java.io.FileOutputStream(file);
			out.write(stringbuilder.toString().getBytes());
			out.flush();
			out.close();

		} catch (Exception me) {
			me.printStackTrace();
		}

		return reportfile;

	}

	private String markupTags(String s) {
		String str = replace(s, "&", "&amp;");
		str = replace(str, "<", "&lt;");
		str = replace(str, ">", "&gt;");
		str = replace(str, "\"", "&quot;");
		str = replace(str, "\r\n", "&lt;br&gt;");
		str = replace(str, "\n", "&lt;br&gt;");
		str = replace(str, "'", "&apos;");
		return str;
	}

	private String replace(String s1, String s2, String s3) {
		if (s1 == null)
			return null;

		int inc = s3.length() - s2.length();
		int offset = 0;
		int fromIndex = 0;
		int findIndex = s1.indexOf(s2, fromIndex);
		StringBuffer buf = new StringBuffer(s1);
		while (findIndex != -1) {
			buf.delete(findIndex + offset, findIndex + offset + s2.length());
			buf.insert(findIndex + offset, s3);
			offset += inc;
			fromIndex = findIndex + s2.length();
			findIndex = s1.indexOf(s2, fromIndex);
		}

		String result = buf.toString();
		return result;
	}

	synchronized private boolean mkdirs(String path) {
		boolean flag = true;
		File file = new File(path);
		if (!file.exists()) {
			flag = file.mkdirs();
		}
		return flag;
	}

	String section508a_img_noalt = "section508(a),need alt for img tag";
	String section508a_tiles_noalt = "section508(a),need alt for tiles";
	String section508a_object = "section508(a),longdesc not empty, no codebase, or no noembed tag in embed";
	String section508a_css_background = "section508(a),don't use background in css";
	String section508a_iframe_title_alternate = "section508(a),no title or alternate content";
	String section508a_ac360iframe_title = "section508(a),no title  in 360 iframe tag";
	String section508a_script_noscripttag = "section508(a),noscript tag after script tag";
	String section508a_frameset = "section508(a),no title or no noframes tag";
	String section508a_applet = "section508(a),no alt or no codebase";
	String section508a_font = "section508(a),use em instead of px and pt for font size";
	String section508a_ac360 = "section508(a),html:element hasn't 'altkey,alt,titlekey,title' attribute;html:elment can't find associated html:label";
	String section508a_form = "section508(a),html:element hasn't 'altkey,alt,titlekey,title' attribute;html:elment can't find associated html:label";
	String section508a_javascript = "section508(a),img,div,span can't have onclick event; no onfocus if have onmouseover; no onblur if have onmouseout;no onkeydown if have onmousedown;nokeyup if have onmouseup";
	String section508a_htmlerrors = "section508(a), no property attribute in html:errors, no element's id,styleid,property attrubite is related with html:errors's property";
	String section508a_doublealttitle = "section508(a), more than one alt or title attribute, contain alt and title attbute";
	String summaryFile = "./section508/";

}

abstract class Section508Policy {
	long starttime = System.currentTimeMillis();
	String name = "";
	String reportfile = "";
	String desc = "";
	String excludes = "";
	Vector reports = new Vector();
	int errorFileCount = 0;
	int correctFileCount = 0;
	int errorCount = 0;

	public abstract Vector verify(String content, String filename);

	public void addScanReport(Object obj) {
		reports.add(obj);
	}

	public boolean isExclude(String filepath) {
		if (this.excludes.length() == 0) {
			return false;
		}
		// check exclude
		filepath = filepath.replace("\\", "/");
		String[] excludes = this.excludes.split(",");
		for (int i = 0; i < excludes.length; i++) {
			Pattern p = Pattern.compile(excludes[i], Pattern.CASE_INSENSITIVE);
			if (p.matcher(filepath).find()) {
				return true;
			}
		}
		return false;
	}

	public Vector fetchTags(String content, String splitPattern, boolean usecut) {
		Vector tags = new Vector();
		Pattern p = Pattern.compile(splitPattern, Pattern.CASE_INSENSITIVE);
		Matcher m = p.matcher(content);

		int curPos = -1;
		int prePos = -1;
		while (true) {
			boolean find = m.find();
			if (usecut) {
				if (!find) {
					if (curPos != -1) {
						String tag = content.substring(curPos);
						tags.add(tag);
					}
					break;
				}

				prePos = curPos;
				curPos = m.start();
				if (prePos != -1 && curPos != -1) {
					String tag = content.substring(prePos, curPos);
					tags.add(tag);
				}
			} else {
				if (find) {
					tags.add(m.group());
				} else {
					break;
				}
			}
		}
		return tags;
	}

	public Vector fetchTags(String content, String startPattern,
			String endPattern, int flag) {
		Vector tags = new Vector();
		Pattern p = Pattern.compile(startPattern, Pattern.CASE_INSENSITIVE);
		Pattern p1 = Pattern.compile(endPattern, Pattern.CASE_INSENSITIVE);
		Matcher m = p.matcher(content);
		Matcher m1 = p1.matcher(content);
		if (flag == 1) {
			int startPos = -1;
			int endPos = -1;
			while (true) {
				boolean find = m.find();
				boolean find1 = m1.find();
				if (!find || !find1) {
					break;
				}

				startPos = m.start();
				endPos = m1.start();

				String tag = "";
				try{
					tag = content.substring(startPos, endPos + endPattern.length());
				}catch(Exception me){
					content = content.substring(endPos + endPattern.length());
					m = p.matcher(content);
					m1 = p1.matcher(content);
				}
				if(tag.length()>0){
					tags.add(tag);
				}

			}
		}
		if (flag == 2) {
			int startPos = -1;
			int endPos = -1;
			while (true) {
				boolean find = m.find();
				boolean find1 = m1.find();
				if (!find || !find1) {
					break;
				}

				startPos = m.start();
				endPos = m1.start();
				String tag = content.substring(startPos, endPos
						+ endPattern.length());
				Matcher temp = p.matcher(tag.substring(startPattern.length()));
				int i = 0;
				while (true) {
					if (temp.find()) {
						i++;
					} else {
						break;
					}
				}
				for (int j = 0; j < i; j++) {
					if (m1.find() && m.find()) {
						endPos = m1.start();
					}
				}
				tag = content.substring(startPos, endPos + endPattern.length());
				tags.add(tag);

			}
		}
		return tags;
	}

	public Vector verify(String content, String splitdata, boolean usecut,
			String[] finddata, boolean any, boolean positive) {
		Vector errors = new Vector();

		Pattern p = Pattern.compile(splitdata, Pattern.CASE_INSENSITIVE);

		Matcher m = p.matcher(content);

		Vector tags = fetchTags(content, splitdata, usecut);
		for (int i = 0; i < tags.size(); i++) {
			String tag = (String) tags.get(i);
			Section508Error error = new Section508Error(tag, desc);
			errors.addAll(verify(tag, finddata, any, positive, true));
		}
		return errors;
	}

	public int matchCount(String content,String [] finddata,boolean usePattern){
		int count = 0;
		for(int i=0; i<finddata.length; i++){
			Pattern p = null;
			if(finddata[i]==null){
				continue;
			}
			if(usePattern){
				p = Pattern.compile(finddata[i], Pattern.CASE_INSENSITIVE);
				if(p.matcher(content).find()){
					count ++;
				}
			}else{
				if(content.indexOf(finddata[i])>=0){
					count ++;
				}
			}
		}
		return count;
	}
	public Vector verify(String content, String[] finddata, boolean any,
			boolean positive, boolean usePattern) {
		Vector errors = new Vector();
		boolean isError = false;
		boolean isFind = false;
		Section508Error error = new Section508Error(content, desc);
		for (int i = 0; i < finddata.length; i++) {
			Pattern p =  null;
			if(finddata[i]==null){
				continue;
			}
			if (usePattern) {
				p = Pattern.compile(finddata[i], Pattern.CASE_INSENSITIVE);
				if (positive) {
					if (any) {
						if (!p.matcher(content).find()) {
							isError = true;
							break;
						} else {
							isError = false;
						}
					} else {
						if (p.matcher(content).find()) {
							isError = false;
							break;
						} else {
							isError = true;
						}
					}
				} else {
					if (any) {
						if (p.matcher(content).find()) {
							isError = true;
							break;
						} else {
							isError = false;
						}
					} else {
						if (!p.matcher(content).find()) {
							isError = false;
							break;
						} else {
							isError = true;
						}
					}
				}
			} else {
				if (positive) {
					if (any) {
						if (content.indexOf(finddata[i]) == -1) {
							isError = true;
							break;
						} else {
							isError = false;
						}
					} else {
						if (content.indexOf(finddata[i]) != -1) {
							isError = false;
							break;
						} else {
							isError = true;
						}
					}
				} else {
					if (any) {
						if (content.indexOf(finddata[i]) != -1) {
							isError = true;
							break;
						} else {
							isError = false;
						}
					} else {
						if (content.indexOf(finddata[i]) == -1) {
							isError = false;
							break;
						} else {
							isError = true;
						}
					}

				}
			}
		}
		if (isError) {
			errors.add(error);
		}
		return errors;
	}

}

class JavascriptPolicy extends Section508Policy {
    public static int count = 0;
    Hashtable typesHash = new Hashtable();
    
    
	public Vector verify(String content, String verifyfile) {


		Vector errors = new Vector();
		Vector elements = new Vector();
		
		String [] focusPattern = new String[]{"<img.* onclick=.*>","<div.* onclick=.*>","<span.* onclick=.*>","<html:image.* onclick=.*>"};
		String [] onclickPattern = new String[]{" onclick=.*"};
		for(int i=0; i< focusPattern.length; i++){
			elements.addAll(fetchTags(content, focusPattern[i], false));
		}
		
		for(int i=0; i<elements.size(); i++){
			String temp = (String)elements.get(i);
			int pos = temp.indexOf(">");
			if(pos!=-1){
				temp = temp.substring(0,pos+1);
				errors.addAll(this.verify(temp, onclickPattern, false, false, true));
			}
		}
		
		elements.clear();
		String [] inputsPattern = new String[]{"<input .*>","<html:[^s].*>"};
		String [] blursPattern = new String[]{"onfocus=.*blur().*"};
		for(int i=0; i<inputsPattern.length; i++){
			elements.addAll(fetchTags(content,inputsPattern[i],false));
			
		}
		for(int i=0; i< elements.size(); i++){
			String temp = (String)elements.get(i);
			int pos = temp.indexOf(">");
			if(pos!=-1){
				temp = temp.substring(0,pos+1);
				errors.addAll(this.verify(temp, blursPattern, false, false, true));
			}
			
		}
		

		elements.clear();
		String aPattern = "<a.*>.*</a>";
		elements = this.fetchTags(content, aPattern, false);
		
		String onmousemovePattern = " onmouseover=.*";
		String onfocusPattern = " onfocus=.*";
		
		
		String onmouseoutPattern = " onmouseout=.*";
		String onblurPattern = " onblur=.*" ;
		
		
		String onmousedownPattern = " onmousedown=.*";
		String onkeydownPattern = " onkeydown=.*";
		
		String onmouseupPattern = " onmouseup=.*";
		String onkeyupPattern = " onkeyup=.*";
		
		String [] ignoresPatterns = new String[]{".*window.status.*",".*pushbtn.*"};
		
		
		for(int i=0; i<elements.size();i++){
			boolean ignoreonmouseover = false;
			boolean ignoreonmouseout = false;
			boolean ignoreonmousedown = false;
			boolean ignoreonmouseup = false;
			
			String temp = (String)elements.get(i);
			temp = temp.replaceAll("[\r\n\t]", " ")
			.replaceAll(" +", " ").toLowerCase();
			String t = "";
			StringTokenizer tokens = new StringTokenizer(temp," =/>\"'\\");	
			while(tokens.hasMoreTokens()){
				String token = tokens.nextToken();
				if(token.equalsIgnoreCase("onmouseout")){
					if(tokens.hasMoreTokens()){
						t = tokens.nextToken();
						t = t.replace("\\", "").toLowerCase();
						if(this.verify(t, ignoresPatterns, false, true, true).size()==0){
							ignoreonmouseout = true;
						}
						continue;
					}
				}
				if(token.equalsIgnoreCase("onmouseover")){
					if(tokens.hasMoreTokens()){
						t = tokens.nextToken();
						t = t.replace("\\", "").toLowerCase();
						if(this.verify(t, ignoresPatterns, false, true, true).size()==0){
							ignoreonmouseover = true;
						}
						continue;
					}
				}	
				if(token.equalsIgnoreCase("onmousedown")){
					if(tokens.hasMoreTokens()){
						t = tokens.nextToken();
						t = t.replace("\\", "").toLowerCase();
						if(this.verify(t, ignoresPatterns, false, true, true).size()==0){
							ignoreonmousedown = true;
						}
						continue;
					}
				}
				if(token.equalsIgnoreCase("onmouseup")){
					if(tokens.hasMoreTokens()){
						t = tokens.nextToken();
						t = t.replace("\\", "").toLowerCase();
						if(this.verify(t, ignoresPatterns, false, true, true).size()==0){
							ignoreonmouseup = true;
						}
						continue;
					}
				}				
			}
			if(!ignoreonmouseover && this.fetchTags(temp, onmousemovePattern, false).size()>0 && this.fetchTags(temp, onfocusPattern, false).size()==0){			
				errors.add(new Section508Error(temp,desc));
			}
			if(!ignoreonmouseout && this.fetchTags(temp, onmouseoutPattern, false).size()>0 && this.fetchTags(temp, onblurPattern, false).size()==0){
				errors.add(new Section508Error(temp,desc));
			}
			if(!ignoreonmousedown && this.fetchTags(temp, onmousedownPattern, false).size()>0 && this.fetchTags(temp, onkeydownPattern, false).size()==0){
				errors.add(new Section508Error(temp,desc));
			}
			if(!ignoreonmouseup && this.fetchTags(temp, onmouseupPattern, false).size()>0 && this.fetchTags(temp, onkeyupPattern, false).size()==0){
				errors.add(new Section508Error(temp,desc));
			}			
		}
			       	
		// output report
		errorCount = errorCount + errors.size();
		if (errors.size() > 0) {
			this.errorFileCount++;
		} else {
			this.correctFileCount++;
		}
		return errors;
	}		
}

class HtmlFormPolicy extends Section508Policy {
        public static int count = 0;
        Hashtable typesHash = new Hashtable();
        
		public Vector verify(String content, String verifyfile) {
			if(verifyfile.indexOf("act_AutoGenParams.jsp")>0){
				System.out.println(verifyfile);
			}
			Vector errors = new Vector();
			String inputPattern = "<input .*>";
			String labelPattern = "<label .*>";
			String beanlabelPattern = "<bean:label.*";
			String selectPattern = "<select ";
			String selectPattern1 = "</select>";
			content = content.replace("<input ", "\r\n<input ");
			content = content.replace("<INPUT ", "\r\n<input ");
			content = content.replace("<label ", "\r\n<label ");
			content = content.replace("<LABEL ", "\r\n<label ");
			content = content.replace("<bean:label", "\r\n<bean:label");
			content = content.replace("<BEAN:LABEL", "\r\n<bean:label");

			
			Vector labelElements = this.fetchTags(content, labelPattern, false);
			Vector beanlabelElements = this.fetchTags(content, beanlabelPattern, false);
			labelElements.addAll(beanlabelElements);
			
			Vector inputElements =  new Vector();
			
			Vector v = fetchTags(content, selectPattern, selectPattern1,1);
			//add select elements
			for(int i=0; i<v.size(); i++){
				String temp = (String)v.get(i);
				if(temp.indexOf(" disabled=\"true\"")>0 || temp.indexOf("style=\"display:none;\"")>0){
					continue;
				}else{
					inputElements.add(temp);
				}
			}

			
			v = fetchTags(content, inputPattern,false);
			//add input element
			for(int i=0; i <v.size(); i++){
				String temp = (String)v.get(i);
				if(temp.indexOf(" disabled=\"true\"")>0 || temp.indexOf("style=\"display:none;\"")>0){
					continue;
				}else{
					inputElements.add(temp);
				}
			}
			
			
			Vector fors = new Vector();
			for(int i=0; i<labelElements.size(); i++){
				
				String labelElement = (String)labelElements.get(i);
				labelElement = labelElement.replace("\\", "").replaceAll("[\r\n\t]", " ")
				.replaceAll(" +", " ").replaceAll("'", "\"").toLowerCase();				
				String forPattern = " for=\".*\"";
				fors.addAll(fetchTags(labelElement, forPattern, false));
			}
			String[] propertyPatterns = new String[fors.size()*2+4];
			String[] onfocusPatterns = new String[]{"onfocus=.*blur().*"};
			propertyPatterns[0] = "title=";
			propertyPatterns[1] = "titlekey=";
			propertyPatterns[2] = "alt=";
			propertyPatterns[3] = "altkey=";
			for (int b = 0; b < fors.size(); b++) {
				String t = ((String)fors.get(b)).toLowerCase().trim();
				
				int pos1 = 0;
				int pos2 = 0;
				if(t.indexOf("for=\"<%=")==-1 && t.indexOf("\"%>\"")==-1){
					pos1 = t.indexOf("for=");
					pos2 = t.indexOf("\"", pos1+5);
					try{
						if(pos2==-1){
							t = t.substring(pos1+4);
						}else{
							t = (t.substring(pos1+4,pos2+1));
						}
					}catch(Exception me){
						me.printStackTrace();
					}
					
					propertyPatterns[b+4] = " id=" + t;
					if(t.startsWith("\"") && t.endsWith("\"") && t.length()>2){
						try{
							t = t.substring(1,t.length()-1);
						}catch(Exception me){
							me.printStackTrace();
						}
					}
					propertyPatterns[b+4+fors.size()] = " id=" + t;
				}else{
					pos1 = t.indexOf("for=\"<%=");
					pos2 = t.indexOf("%>\"");
					try{
						if(pos2==-1){
							t = t.substring(pos1+4);
						}else{						
							t = (t.substring(pos1+4,pos2+1));
						}
					}catch(Exception me){
						me.printStackTrace();
					}
					propertyPatterns[b+4] = " id=" + t;
					if(t.startsWith("\"") && t.endsWith("\"") && t.length()>2){
						t = t.substring(1,t.length()-1);
					}
					propertyPatterns[b+4+fors.size()] = " id=" + t;					
				}
			}
			
			Hashtable ignoreHash = new Hashtable();
			ignoreHash.put("hidden", "hidden");
			ignoreHash.put("button", "button");
			ignoreHash.put("submit", "submit");
			
			for(int i=0; i<inputElements.size(); i++){
				String inputElement = (String)inputElements.get(i);
				inputElement = inputElement.replace("\\", "").replaceAll("[\r\n\t]", " ")
				.replaceAll(" +", " ").replaceAll("'", "\"").replaceAll("id\\s*=", "id=").toLowerCase();
				
				StringTokenizer tokens = new StringTokenizer(inputElement," =/>\"'\\");
				String type = "text";
				
				while(tokens.hasMoreTokens()){
					String token = (String)tokens.nextToken();
					if(token.equalsIgnoreCase("type")){
						if(tokens.hasMoreTokens()){
							type = tokens.nextToken();
							type = type.replace("\\", "").toLowerCase();
							break;
						}
					}
					
				}
				if (ignoreHash.contains(type)) {
					continue;
				}   
				errors.addAll(verify(inputElement, propertyPatterns, false,
						true, false));
							
				if(!typesHash.contains(type.toLowerCase())){
					typesHash.put(type.toLowerCase(), type.toLowerCase());
				}

			}
		
			// output report
			errorCount = errorCount + errors.size();
			if (errors.size() > 0) {
				this.errorFileCount++;
			} else {
				this.correctFileCount++;
			}
			return errors;
		}		
}

class DoubleAltTitlePolicy extends Section508Policy {
	public Vector verify(String content,String verifyfile){
		Vector errors = new Vector();
		String htmlPattern = "<html:.*>";
		String inputPattern = "<input .*>";
		String selectPattern = "<select ";
		String selectPattern1 = "</select>";	
		String imgPattern = "<img .*[^%]>";
		
		String appletPattern = "<applet .*>";
		
		String framesetPattern = "<frameset";
		String framesetPattern1 = "</frameset>";
		String framePattern = "<frame ";
		
		String iframePattern = "<iframe ";
		String iframePattern1 = "</iframe>";
		
		
		String [] tipPatterns = new String[]{"alt=","altkey=","title=","titlekey="};		

		//add iframe 
		Vector elements = fetchTags(content, iframePattern, iframePattern1,1);
		
		//add applet
		elements.addAll(fetchTags(content,appletPattern,false));
		
		//add img
		elements.addAll(fetchTags(content,imgPattern,false));
		
		//add html:xxx
		elements.addAll(fetchTags(content,htmlPattern,false));
		
		//add html:xxx
		elements.addAll(fetchTags(content,inputPattern,false));
		
		//add select
		elements.addAll(fetchTags(content,selectPattern,selectPattern1,1));
		
		for(int i=0; i<elements.size(); i++){
			String element = (String)elements.get(i);
			int count = this.matchCount(element, tipPatterns, true);
			if(count>1){
				errors.add(new Section508Error(element,desc));
			}
		}
		
		return errors;
	}
	
}
class ErrorsPolicy extends Section508Policy{
	public Vector verify(String content, String verifyfile) {

		if(verifyfile.indexOf("addressSearch4Asset.jsp")>0){
			System.out.println("addressSearch4Asset.jsp");
		}
		Vector errors = new Vector();
		Vector elements = new Vector();
		Vector htmlerrors = new Vector();
		
		String inputPattern = "<input .*[^%]>>";
		String labelPattern = "<label .*[^%]>>";
		String beanlabelPattern = "<bean:label.*[^%]>";
		String selectPattern = "<select ";
		String selectPattern1 = "</select>";
		String htmlPattern = "<html:.*[^%]>";
		String [] ac360tagPattern = new String[]{"<AC360:countryList","</AC360:countryList>"};


		Vector temp = fetchTags(content, htmlPattern, false);
		for(int i=0; i< temp.size(); i++){
			String s = (String)temp.get(i);
			if(s.startsWith("<html:errors")){
				htmlerrors.add(s);
			}else{
				elements.add(s);
			}
			
		}
		if(htmlerrors.size()==0){
			return new Vector();
		}
		Vector labels  = new Vector();
		labels.addAll(fetchTags(content, labelPattern, false));
		labels.addAll(fetchTags(content, beanlabelPattern, false));
		
		Hashtable fors = new Hashtable();
		for(int i=0; i<labels.size(); i++){
			String s = (String)labels.get(i);
			String f = getAttribute(s, "for=");
			if(f!=null && f.length()>0){
				fors.put(f, f);
			}
		}
		elements.addAll(labels);
		elements.addAll(fetchTags(content, selectPattern, selectPattern1,1));
		elements.addAll(fetchTags(content, inputPattern,false));
		
		for(int i=0; i< ac360tagPattern.length; i=i+2){
			elements.addAll(fetchTags(content,ac360tagPattern[i],ac360tagPattern[i+1],1));
		}
		if(elements.size()==0){
			return new Vector();
		}

		
		//get id,styleid,property
		Hashtable keys = new Hashtable();
		for(int i=0; i< elements.size(); i++){
			keys.putAll(getKeys((String)elements.get(i)));
		}
		
		for(int i=0; i< htmlerrors.size(); i++){			
			String s = (String)htmlerrors.get(i);
			Section508Error error = new Section508Error(s, desc);
			String property = getPropertyKey(s);
			String lablefor = getAttribute(s, "labelfor=");
			if(property.indexOf("value(err_msg)")>-1){
				continue;
			}
			if(((property==null || property.length()==0) && (lablefor==null || lablefor.length()==0) )|| (!keys.containsKey(property) && !fors.containsKey(lablefor))){
				errors.add(error);
			}						
		}
			
		// output report
		errorCount = errorCount + errors.size();
		if (errors.size() > 0) {
			this.errorFileCount++;
		} else {
			this.correctFileCount++;
		}
		return errors;
	}	
	
	String getAttribute(String element,String attribute){
		//replace <%=  %>
		element = element.replace("<%=", "$");
		element = element.replace("%>", "$$");
		String key = "";
		
		StringTokenizer tokens = new StringTokenizer(element," />");
		while(tokens.hasMoreElements()){
			String token= tokens.nextToken().toLowerCase();
			if(token.startsWith(attribute)){
					key = token.substring(attribute.length()+1);
						//handle \"
						key = key.replace("\\", "");
						//revmoe "
						if(key.startsWith("\"") && key.endsWith("\"") && key.length()>2){
							key = key.substring(1,key.length()-1);
						}
						if(key.startsWith("'") && key.endsWith("'") && key.length()>2){
							key = key.substring(1,key.length()-1);
						}
						
						key = key.replace("$$", "%>");
						key = key.replace("$", "<%=");
						//if(key.indexOf(" ")>0 || key.indexOf("\"")>0 || key.indexOf("'")>0){

			}
		}
		return key;		
	}
	String getPropertyKey(String element){
		//replace <%=  %>
		element = element.replace("<%=", "$");
		element = element.replace("%>", "$$");
		String key = "";
		
		StringTokenizer tokens = new StringTokenizer(element," />");
		while(tokens.hasMoreElements()){
			String token= tokens.nextToken().toLowerCase();
			if(token.startsWith("property=")){
					key = token.substring(token.indexOf("=")+1);
						//handle \"
						key = key.replace("\\", "");
						//revmoe "
						if(key.startsWith("\"") && key.endsWith("\"") && key.length()>2){
							key = key.substring(1,key.length()-1);
						}
						if(key.startsWith("'") && key.endsWith("'") && key.length()>2){
							key = key.substring(1,key.length()-1);
						}
						
						key = key.replace("$$", "%>");
						key = key.replace("$", "<%=");

			}
		}
		return key;
	}
	
	
	Hashtable getKeys(String element){
		Hashtable hash = new Hashtable();
		//replace <%=  %>
		element = element.replace("<%=", "$");
		element = element.replace("%>", "$$");
		
		StringTokenizer tokens = new StringTokenizer(element," />");
		while(tokens.hasMoreElements()){
			String token= tokens.nextToken().toLowerCase();
			String key = "";
			if(token.startsWith("id=") || token.startsWith("styleid=") || token.startsWith("property=") ){
					    key = token.substring(token.indexOf("=")+1);
						//handle \"
						key = key.replace("\\", "");
						//revmoe "
						if(key.startsWith("\"") && key.endsWith("\"") && key.length()>2){
							key = key.substring(1,key.length()-1);
						}
						key = key.replace("$$", "%>");
						key = key.replace("$", "<%=");
						if(!hash.containsKey(key)){
							hash.put(key, key);
						}
						
			}
		}
		return hash;
	}
}

class AC360Policy extends Section508Policy {
	Hashtable tagHash = new Hashtable();

	public Vector verify(String content, String verifyfile) {

		
		Vector errors = new Vector();

		String ac360Pattern = "<AC360:element";
		String ac360Pattern1 = "</AC360:element>";


		Hashtable ignoreHash = new Hashtable();
		ignoreHash.put("<html:option", "<html:option");
		ignoreHash.put("<html:options", "<html:options");
		ignoreHash.put("<html:link", "<html:link");
		ignoreHash.put("<html:hidden", "<html:hidden");
		ignoreHash.put("<html:multibox", "<html:multibox");
		ignoreHash.put("<html:errors", "<html:errors");
		String htmlLabelPattern = "<label .*>";
		
		String htmlPattern = "<html:.*[^%]>";
		String labelPattern = "<bean:label.*/>";
		Vector elements = this.fetchTags(content, ac360Pattern, ac360Pattern1,
				1);

		for (int i = 0; i < elements.size(); i++) {
			String element = (String) elements.get(i);
			Vector htmlElements = this.fetchTags(element, htmlPattern, false);
			Vector labels = this.fetchTags(element, labelPattern, false);
			labels.addAll(this.fetchTags(element, htmlLabelPattern, false));
			Vector fors = new Vector();
			for (int k = 0; k < labels.size(); k++) {
				String labelElement = (String) labels.get(k);
				labelElement = labelElement.replaceAll("[\r\n\t]", " ")
						.replaceAll(" +", " ");
				String forPattern = " for=\".*\"";
				String[] patterns = new String[] { forPattern };
				fors.addAll(this.fetchTags(labelElement, forPattern, false));
			}
			
			String[] propertyPatterns = new String[fors.size()+4];
			propertyPatterns[0] = " title=";
			propertyPatterns[1] = " titlekey=";
			propertyPatterns[2] = " alt=";
			propertyPatterns[3] = " altkey=";
			
			String[] onfocusPatterns = new String[]{"onfocus=.*blur().*"};
			
			for (int b = 0; b < fors.size(); b++) {
				String t = ((String)fors.get(b)).toLowerCase();
				int pos1 = t.indexOf("for=");
				int pos2 = t.indexOf("\"", pos1+5);
				propertyPatterns[b+4] = " property=" + (t.substring(pos1+4,pos2));
			}

			
			for (int j = 0; j < htmlElements.size(); j++) {
				String htmlElement = (String) htmlElements.get(j);
				htmlElement = htmlElement.replaceAll("[\r\n\t]", " ")
						.replaceAll(" +", " ").toLowerCase();
				int pos = htmlElement.indexOf(" ");
				String htmlTag = htmlElement.trim();
				if (pos != -1) {
					htmlTag = htmlElement
							.substring(0, htmlElement.indexOf(" "));
				}
				
				if (ignoreHash.contains(htmlTag)) {
					continue;
				}
								
				errors.addAll(verify(htmlElement, propertyPatterns, false,
						true, false));
			}

		}
		// output report
		errorCount = errorCount + errors.size();
		if (errors.size() > 0) {
			this.errorFileCount++;
		} else {
			this.correctFileCount++;
		}
		return errors;
	}
}

class FontPolicy extends Section508Policy {
	public Vector verify(String content, String verifyfile) {
		Vector errors = new Vector();
		String ptPattern = "[^-]font-size: *\\d+p[tx];";
		String[] finddata = new String[] { "\\D1\\s*p[tx];"};
		try {
			//ignore 1pt,1px
			errors.addAll(verify(content, ptPattern, false, finddata, true,
					true));
		} catch (Exception me) {
			me.printStackTrace();
		}
		// output report
		errorCount = errorCount + errors.size();
		if (errors.size() > 0) {
			this.errorFileCount++;
		} else {
			this.correctFileCount++;
		}
		return errors;
	}
}

class AppletPolicy extends Section508Policy {
	public Vector verify(String content, String verifyfile) {
		Vector errors = new Vector();
		try {

			String appletPattern = "<applet .*>";
			String altPattern = " alt\\W";
			String codebasePattern = " codebase\\W";

			String[] findPattern = new String[] { altPattern, codebasePattern };

			Pattern p = Pattern
					.compile(appletPattern, Pattern.CASE_INSENSITIVE);

			Matcher m = p.matcher(content);

			Vector tags = this.fetchTags(content, appletPattern, false);
			for (int i = 0; i < tags.size(); i++) {
				String tag = (String) tags.get(i);
				errors.addAll(verify(tag, findPattern, true, true, true));
			}
			// output report
			errorCount = errorCount + errors.size();
			if (errors.size() > 0) {
				this.errorFileCount++;
			} else {
				this.correctFileCount++;
			}

		} catch (Exception me) {
			me.printStackTrace();
		}
		return errors;
	}
}

class FramesetPolicy extends Section508Policy {
	public Vector verify(String content, String verifyfile) {
		Vector errors = new Vector();
		try {

			String framesetPattern = "<frameset";
			String framesetPattern1 = "</frameset>";
			String framePattern = "<frame ";
			String[] noframesPattern = new String[] { "<noframes",
					"</noframes>" };
			String[] titlePattern = new String[] { "title=",
					"asiTableValueMapTreeTitle", "asiTableValueMapListTitle" };

			Pattern p = Pattern.compile(framesetPattern,
					Pattern.CASE_INSENSITIVE);
			Pattern p1 = Pattern
					.compile(framePattern, Pattern.CASE_INSENSITIVE);

			Matcher m = p.matcher(content);

			Vector tags = this.fetchTags(content, framesetPattern,
					framesetPattern1, 2);
			for (int i = 0; i < tags.size(); i++) {
				String tag = (String) tags.get(i);
				errors.addAll(verify(tag, framePattern, true, titlePattern,
						false, true));
				errors.addAll(verify(tag, noframesPattern, true, true, true));
			}
			// output report
			errorCount = errorCount + errors.size();
			if (errors.size() > 0) {
				this.errorFileCount++;
			} else {
				this.correctFileCount++;
			}

		} catch (Exception me) {
			me.printStackTrace();
		}
		return errors;
	}
}

class CssPolicy extends Section508Policy {
	public Vector verify(String content, String verifyfile) {
		Vector errors = new Vector();
		try {

			String backgroundPattern = "background:url.*;";
			Pattern p1 = Pattern.compile(backgroundPattern,
					Pattern.CASE_INSENSITIVE);
			String data = "";

			data = content;

			// check background
			Matcher m;
			m = p1.matcher(data);

			while (true) {
				boolean find = m.find();
				if (!find) {
					break;
				} else {
					String tag = m.group();
					Section508Error error = new Section508Error(tag, desc);
					errors.add(error);
				}
			}

			// output report
			errorCount = errorCount + errors.size();
			if (errors.size() > 0) {
				this.errorFileCount++;
			} else {
				this.correctFileCount++;
			}
		} catch (Exception me) {
			me.printStackTrace();
		}
		return errors;
	}
}

class NoscriptPolicy extends Section508Policy {
	public Vector verify(String content, String verifyfile) {
		Vector errors = new Vector();
		try {

			String scriptPattern = "<script>";
			String noscriptPattern = "<noscript>";
			Pattern p = Pattern
					.compile(scriptPattern, Pattern.CASE_INSENSITIVE);
			Pattern p1 = Pattern.compile(noscriptPattern,
					Pattern.CASE_INSENSITIVE);

			Matcher m = p.matcher(content);

			int curPos = -1;
			int prePos = -1;
			while (true) {
				boolean find = m.find();
				if (!find) {
					if (curPos != -1) {
						String tag = content.substring(curPos);
						Section508Error error = new Section508Error(tag, desc);
						if (!p1.matcher(tag).find()) {
							errors.add(error);
						}
					}
					break;
				}
				prePos = curPos;
				curPos = m.start();
				if (prePos != -1 && curPos != -1) {
					String tag = content.substring(prePos, curPos);
					Section508Error error = new Section508Error(tag, desc);
					if (!p1.matcher(tag).find()) {
						errors.add(error);
					}
				}
			}

			// output report
			errorCount = errorCount + errors.size();
			if (errors.size() > 0) {
				this.errorFileCount++;
			} else {
				this.correctFileCount++;
			}

		} catch (Exception me) {
			me.printStackTrace();
		}
		return errors;
	}
}

class IframePolicy extends Section508Policy {
	public Vector verify(String content, String verifyfile) {
		Vector errors = new Vector();
		try {

			String iframePattern = "<iframe ";
			String iframePattern1 = "</iframe>";

			Vector elements = this.fetchTags(content, iframePattern, iframePattern1,1);
			
			String [] titlePattern = new String [] {"title="};
			String [] alternatePattern = new String[]{"<a ","section508.iframenonsupportmessage.label"};

	        for(int i=0; i<elements.size(); i++){
	        	String iframe = (String)elements.get(i);
	        	Vector v = verify(iframe, titlePattern, true, true, true);
	        	if(v.size()>0){
	        		errors.addAll(v);
	        	}else{
	        		errors.addAll(verify(iframe, alternatePattern, false, true, true));
	        	}	
	        }

			// output report
			errorCount = errorCount + errors.size();
			if (errors.size() > 0) {
				this.errorFileCount++;
			} else {
				this.correctFileCount++;
			}
		} catch (Exception me) {
			me.printStackTrace();
		}
		return errors;
	}
}

class ObjectPolicy extends Section508Policy {
	public Vector verify(String content, String verifyfile) {
		Vector errors = new Vector();
		try {
			String objectPattern = "<OBJECT ";
			String longdescPattern = "longdesc=\"*\"";
			String codebasePattern = "codebase=";
			String[] findPattern = new String[] { codebasePattern };
			String[] notfindPattern = new String[] { longdescPattern };
			String embedPattern = "<embed";
			String[] noembedPattern = new String[] { "<noembed" };
			Pattern p = Pattern
					.compile(objectPattern, Pattern.CASE_INSENSITIVE);
			Pattern p1 = Pattern.compile(longdescPattern,
					Pattern.CASE_INSENSITIVE);

			Matcher m = p.matcher(content);

			Vector tags = fetchTags(content, objectPattern, true);
			for (int i = 0; i < tags.size(); i++) {
				String tag = (String) tags.get(i);
				errors.addAll(this.verify(tag, findPattern, true, true, true));
				errors.addAll(this.verify(tag, notfindPattern, true, false,
						true));
				errors.addAll(this.verify(tag, embedPattern, true,
						noembedPattern, true, true));
			}
			// output report
			errorCount = errorCount + errors.size();
			if (errors.size() > 0) {
				this.errorFileCount++;
			} else {
				this.correctFileCount++;
			}

		} catch (Exception me) {
			me.printStackTrace();
		}
		return errors;
	}
}

class ImgPolicy extends Section508Policy {

	public Vector verify(String content, String verifyfile) {
		Vector errors = new Vector();
		try {
			
			String imgPattern = "<img .*[^%]>";
			String [] altPattern = new String[] {"\\salt\\s?=","\\stitle\\s?="};
			Pattern p = Pattern.compile(imgPattern, Pattern.CASE_INSENSITIVE);
			
			errors.addAll(verify(content, imgPattern, false, altPattern, false, true));

			// output report
			errorCount = errorCount + errors.size();
			if (errors.size() > 0) {
				this.errorFileCount++;
			} else {
				this.correctFileCount++;
			}

		} catch (Exception me) {
			me.printStackTrace();
		}
		return errors;
	}
}

class Section508Report {
	int errorCounts = 0;
	String reportlink = "";
	String filepath = "";

	public Section508Report(String f, String r, int c) {
		this.filepath = f;
		this.reportlink = r;
		this.errorCounts = c;
	}

}

class Section508Error {
	String errormsg = "";
	String content = "";

	public Section508Error(String c, String msg) {
		content = c;
		errormsg = msg;

	}

}
